#include <gtest/gtest.h>
#include "uniqueptr.hpp"

// 运行测试，确保环境正常后进入正式迭代。
TEST(UniquePtrInitialTest, Compiles) {
    UniquePtr<int> ptr;
    (void)ptr;
}

// 目前删除器先简单保存为 `nullptr`，稍后再完善。
TEST(UniquePtrTest, DefaultConstructedIsNull) {
    UniquePtr<int> ptr;
    EXPECT_EQ(ptr.get(), nullptr);
    EXPECT_FALSE(ptr);
}

TEST(UniquePtrTest, NullptrConstructionBehavesLikeDefault) {
    UniquePtr<int> ptr(nullptr);
    EXPECT_EQ(ptr.get(), nullptr);
    EXPECT_FALSE(ptr);
}

TEST(UniquePtrTest, ConstructWithRawPointerAndAccess) {
    UniquePtr<std::string> ptr(new std::string("hello"));
    EXPECT_TRUE(ptr);
    EXPECT_EQ(ptr.get()->size(), 5U);
    EXPECT_EQ((*ptr)[1], 'e');
    EXPECT_EQ(ptr.operator->()->substr(0, 4), "hell");
}

struct Counter {
    static inline int instances = 0;
    Counter() { ++instances; }
    ~Counter() { --instances; }
};

TEST(UniquePtrTest, ReleasesResourceOnDestruction) {
    EXPECT_EQ(Counter::instances, 0);
    {
        UniquePtr<Counter> ptr(new Counter());
        EXPECT_EQ(Counter::instances, 1);
    }
    EXPECT_EQ(Counter::instances, 0);
}

TEST(UniquePtrTest, ResetReleasesOldAndTakesNew) {
    UniquePtr<int> ptr(new int(10));
    ptr.reset(new int(20));
    ASSERT_NE(ptr.get(), nullptr);
    EXPECT_EQ(*ptr, 20);
}

TEST(UniquePtrTest, ResetWithoutArgReleasesResource) {
    UniquePtr<int> ptr(new int(10));
    ptr.reset();
    EXPECT_EQ(ptr.get(), nullptr);
    EXPECT_FALSE(ptr);
}

TEST(UniquePtrTest, ReleaseReturnsRawPointerWithoutDeleting) {
    UniquePtr<int> ptr(new int(99));
    int* raw = ptr.release();
    EXPECT_EQ(ptr.get(), nullptr);
    EXPECT_FALSE(ptr);
    ASSERT_NE(raw, nullptr);
    EXPECT_EQ(*raw, 99);
    delete raw;
}

TEST(UniquePtrTest, SwapExchangesPointers) {
    UniquePtr<int> a(new int(1));
    UniquePtr<int> b(new int(2));

    a.swap(b);
    EXPECT_EQ(*a, 2);
    EXPECT_EQ(*b, 1);

    swap(a, b);
    EXPECT_EQ(*a, 1);
    EXPECT_EQ(*b, 2);
}